#include <iostream>
#include <sstream>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <vector>
#include "main.h"
#include "WindowStatus.h"
#include "Framework.h"
#include "RenderSystem.h"
#include "IniParser.h"

/* key map*/
#define ESCAPE  27

using namespace std;

WindowStatus    windowStatus;
RenderSystem    renderSystem;
TargetManager   targetManager;
TextureManager  textureManager;

// FPS calculation and time based physics
unsigned int fps_physics=0;
unsigned int fps_rendering=0;
unsigned int set_fps_physics=100;
unsigned int remaining_time=0; // 相对于物理帧的剩余时间
unsigned long fps_count_physics=0; // 物理引擎的帧率
unsigned long fps_count_rendering=0; // 绘制引擎的帧率
unsigned long last_ticks=0; // 自上一帧的tick数
int msecxdframe=1000/set_fps_physics; // 每一物理帧的毫秒数

void WorldInit(void) {

   targetManager.importMeshFromIni("world.ini", "object1"); 
   //targetManager.import3DSFromIni("world.ini", "object2"); 
   //targetManager.import3DSFromIni("world.ini", "object3"); 
}

void MainLoop(void) {
	unsigned long l_start_time;
	unsigned long l_elapsed_time;
	unsigned long l_frame_time;
    //事件处理
    FrameworkEvent();

	// Rendering
	fps_count_rendering++; // Increase rendering FPS counter
	l_start_time = Framework_GetTicks();
    //绘制
    renderSystem.RenderDisplay();

    renderSystem.RenderFpsUpdate(Framework_GetTicks());

	// Elapsed time calculation
	l_elapsed_time=Framework_GetTicks()-l_start_time+remaining_time; // Elapsed time (we add also the previous remaining time)
	l_frame_time=l_elapsed_time / msecxdframe; // Frames quantity we must cycle for physics
	remaining_time=l_elapsed_time % msecxdframe; // Get the remaining time because we are working with integer values


	// Physics
	while (l_frame_time-->0) // Now do physics as many times as we need to match the elapsed time of the rendering phase
	{
		fps_count_physics++; // Increase physics FPS counter

	}//while (l_frame_time-->0)


	// Rendering and Physics FPS calculation
	if ((Framework_GetTicks()-last_ticks)>=1000) // Every second
	{
		last_ticks = Framework_GetTicks(); // Save the current ticks to catch the next second
		// Assings the current FPS count to the global variables
		fps_physics=fps_count_physics;
		fps_rendering=fps_count_rendering;
		// Clear the local counters
		fps_count_physics = 0;
		fps_count_rendering = 0;
	}

}


void KeyboardHandle(unsigned char key, int x, int y) {
    //std::cout << "KeyboardHandle." << std::endl;
    switch(key) {
        case ESCAPE:
            glutDestroyWindow(WindowStatus::getSingletonPtr()->window);
            exit(0);
        default:
            break;
    }
    renderSystem.getCamera()->OnKeyboard(key);
}

void SpecialKeyboardHandle(int key, int x, int y) {
    switch(key) {
        case GLUT_KEY_UP:
        case GLUT_KEY_DOWN:
        case GLUT_KEY_LEFT:
        case GLUT_KEY_RIGHT:
        case GLUT_KEY_PAGE_DOWN:
        case GLUT_KEY_PAGE_UP:
			renderSystem.getCamera()->OnSpecialKeyboard(key);
            break;

        default:
            break;
    }
}


void processMouse(int button, int state, int x, int y) {
	if (state == GLUT_DOWN && button == GLUT_LEFT_BUTTON) {
		;
	}
}


void processMouseActiveMotion(int x, int y) {
	//cout << "processMouseActiveMotion: x: " << x << " y: " << y << endl;
}

void processMousePassiveMotion(int x, int y) {
	//cout << "processMousePassiveMotion: x: " << x << " y: " << y << endl;
}

int main(int argc, char** argv) {

    FrameworkInit(&argc, argv);
    renderSystem.RenderInit();
    WorldInit();

    FrameworkMainLoop();

	return 0;
}
